﻿Imports System.Runtime.InteropServices
Imports System.Drawing
Imports System.IO

Public Class FrmSyncLogic

    Declare Function FlashWindowEx Lib "user32.dll" (ByRef pfwi As FLASHWINFO) As Integer

    <StructLayout(LayoutKind.Sequential)> _
    Structure FLASHWINFO
        Dim cbSize As Integer
        Dim hwnd As System.IntPtr
        Dim dwFlags As Integer
        Dim uCount As Integer
        Dim dwTimeout As Integer
    End Structure

    Private Const FLASHW_STOP As Integer = &H0
    Private Const FLASHW_CAPTION As Integer = &H1
    Private Const FLASHW_TRAY As Integer = &H2
    Private Const FLASHW_ALL As Integer = (FLASHW_CAPTION Or FLASHW_TRAY)
    Private Const FLASHW_TIMER As Integer = &H4
    Private Const FLASHW_TIMERNOFG As Integer = &HC

    Dim DsPreferences As New DataSet
    Dim DsInitDirs As New DataSet
    Dim DsCopyPreferences As New DataSet
    Dim DsCopyInitDirs As New DataSet
    Dim PathApplication As String
    Dim RoboCopyPath As String = ""
    Dim FirstTimeInit As Boolean
    Dim FirstTimeFinish As Boolean
    Dim Administrator As Boolean
    Dim Source As String
    Dim Destination As String
    Dim MyString As String
    Dim BackForm As Boolean
    Dim Minimized As Boolean
    Dim MyStreamReader As StreamReader
    Dim DirectoriesSource() As String
    Dim DirectoriesDestination() As String
    Dim RowCompleted As Boolean
    Dim Time As String
    Dim CountMilisec As Long
    Public DateStarted As Boolean

    Private Sub SyncroLogic_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

        FirstTimeInit = True
        FirstTimeFinish = True
        BackForm = False
        Minimized = False
        RowCompleted = True
        CountMilisec = 0

        If Not IsUserAdministrator() Then

            MsgBox("You must run this application as Administrator", vbInformation, "Advice")
            Application.Exit()

        Else

            Administrator = True

        End If

        CheckXmlFiles()
        CheckFolderRegistriesSolution()

        ReadXml(DsPreferences, AccessFiles.PathXmlFiles + "Preferences.xml")
        ReadXml(DsInitDirs, AccessFiles.PathXmlFiles + "Init_Directories.xml")

        If Not DsInitDirs.Tables.Item(0).Rows.Count = 0 Then

            ShowInitDirectories(DsInitDirs.Tables.Item(0).Rows(0).Item(0).ToString)
            ShowDestinationDirectories(DsInitDirs.Tables.Item(0).Rows(0).Item(1).ToString)

            FbdSource.SelectedPath = DsInitDirs.Tables.Item(0).Rows(0).Item(0).ToString
            FbdDestination.SelectedPath = DsInitDirs.Tables.Item(0).Rows(0).Item(1).ToString

        End If

        DsCopyPreferences = DsPreferences.Copy()
        DsCopyInitDirs = DsInitDirs.Copy()

        DgvFolders1.DataSource = DsPreferences.Tables.Item(0)
        DgvFolders2.DataSource = DsPreferences.Tables.Item(0)

        BtnOkOptions.Enabled = False

    End Sub

    Private Sub ShowInitDirectories(ByVal Directory As String)

        If Directory.Length < 70 Then

            LblDirecSource.Text = Directory

        Else

            LblDirecSource.Text = TrimString(Directory).ToString
            ToTSource.SetToolTip(LblDirecSource, Directory)

        End If

    End Sub

    Private Sub ShowDestinationDirectories(ByVal Directory As String)

        If Directory.Length < 70 Then

            LblDirecDestination.Text = Directory

        Else

            LblDirecDestination.Text = TrimString(Directory).ToString
            ToTDestination.SetToolTip(LblDirecDestination, Directory)

        End If

    End Sub

    Private Sub TbcSyncro_DrawItem(Sender As Object, e As System.Windows.Forms.DrawItemEventArgs) Handles TbcSyncro.DrawItem

        Dim MyPicture As Bitmap = Nothing
        Dim MyStringFormat As New StringFormat
        Dim MyRectangle As Rectangle
        Dim MyFont As Font
        Dim FontBrush As Brush
        Dim Title As String = ""

        Select Case e.Index

            Case 0

                MyPicture = New Bitmap(My.Resources.Sincronizar.ToBitmap)
                Title = "Sync"

            Case 1

                MyPicture = New Bitmap(My.Resources.Carpetas.ToBitmap)
                Title = "Folders"

            Case 2

                MyPicture = New Bitmap(My.Resources.Opciones.ToBitmap)
                Title = "Options"

            Case 3

                MyPicture = New Bitmap(My.Resources.Pantalla.ToBitmap)
                Title = "Output"

            Case 4

                MyPicture = New Bitmap(My.Resources.Acerca_de.ToBitmap)
                Title = "About"

        End Select


        If e.State = DrawItemState.Selected Then

            e.Graphics.FillRectangle(Brushes.Aquamarine, e.Bounds)

        Else

            e.Graphics.FillRectangle(Brushes.WhiteSmoke, e.Bounds)

        End If

        MyFont = New Font("Arial", 11, FontStyle.Regular, GraphicsUnit.Pixel)

        FontBrush = Brushes.Black

        MyStringFormat.Alignment = StringAlignment.Center

        MyRectangle = New Rectangle(e.Bounds.X, e.Bounds.Y + MyPicture.Height + 10, e.Bounds.Width, e.Bounds.Height)

        e.Graphics.DrawString(Title, MyFont, FontBrush, MyRectangle, MyStringFormat)

        e.Graphics.DrawImage(MyPicture, 20, MyRectangle.Y - MyPicture.Height)

    End Sub

    Private Sub TbcSyncro_Deselecting(sender As Object, e As System.Windows.Forms.TabControlCancelEventArgs) Handles TbcSyncro.Deselecting

        If TbcSyncro.SelectedIndex = 1 Then

            If Not RowCompleted Then
                MsgBox("Press the button OK", vbInformation, "Advice")
                e.Cancel = True
            End If

        End If


    End Sub

    Private Sub TbcSyncro_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles TbcSyncro.SelectedIndexChanged

        If TbcSyncro.SelectedIndex = 1 Then

            DgvFolders2.ClearSelection()

        ElseIf TbcSyncro.SelectedIndex = 3 Then

            LoadGridFiles()

        End If

    End Sub

    Private Sub LoadGridFiles()

        Dim MyColumn As DataGridViewColumn
        Dim Directory As DirectoryInfo
        Dim FolderPath As String
        Dim MyFile As FileInfo

        DgvFiles.Rows.Clear()

        FolderPath = AccessFiles.PathRegistriesFolder

        If Not System.IO.Directory.Exists(FolderPath) Then
            Exit Sub
        End If

        Directory = New DirectoryInfo(FolderPath)

        For Each MyFile In Directory.GetFiles("Output_*.txt")

            DgvFiles.Rows.Add(Nothing, MyFile.Name, MyFile.CreationTime, FormatBytes(CDbl(MyFile.Length)))

        Next

        DgvFiles.Sort(DgvFiles.Columns("Creation_Date"), System.ComponentModel.ListSortDirection.Descending)

        For Each MyColumn In DgvFiles.Columns

            MyColumn.SortMode = DataGridViewColumnSortMode.NotSortable
            DgvFiles.ClearSelection()

        Next

    End Sub

    Private Sub BtnSync_Click(sender As System.Object, e As System.EventArgs) Handles BtnSync.Click

        Dim DirectoryPath As String = ""
        Dim DirectorySource() As String = Nothing
        Dim DirectoryDestination() As String = Nothing

        If Not FindRobocopyPath(RoboCopyPath) Then
            MsgBox("The Robocopy file was not found in your C:\ drive", MsgBoxStyle.Critical, "Error")
            Exit Sub
        End If

        If DgvFolders1.Rows.Count = 0 Then
            MsgBox("Select first the folders you want to sync", MsgBoxStyle.Critical, "Error")
            Exit Sub
        End If

        If Not CheckDirectories(DgvFolders1, DirectoryPath) Then

            MsgBox("The folder " + DirectoryPath + " does not exist", MsgBoxStyle.Critical, "Error")
            Exit Sub

        End If

        If Not ComparesDateDirectories(DgvFolders1, DirectorySource, DirectoryDestination) Then

            If MsgBox("The folder: " + ConcatDirectories(DirectoryDestination) + " is more recent than " + _
                    "the folder: " + ConcatDirectories(DirectorySource) + ". Do you want " + _
                    " to sync anyway?", vbYesNo, "Advice") = MsgBoxResult.No Then
                Exit Sub

            End If

        End If

        If MsgBox("The contents of the " + ConcatDirectoriesSource(DgvFolders1) + " folder will be " + _
                  "changed and you can NOT undo the changes. " + _
                  "Are you sure you want to continue?", vbYesNo, "Advice") = MsgBoxResult.No Then
            Exit Sub

        End If

        CountMilisec = 0
        TmrSync.Start()
        PrbSync.Visible = True
        BtnSync.Enabled = False
        BgwSync.RunWorkerAsync()

    End Sub

    ' [System.Diagnostics.DebuggerNonUserCode]

    Private Sub BgwSync_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BgwSync.DoWork

        Dim CounterDirectories As Integer
        Dim MyProcess() As Process
        Dim MyText As String = ""

        BgwSync.WorkerReportsProgress = True

        BgwSync.ReportProgress(10)

        LoadMatrices(DgvFolders1, DirectoriesSource, DirectoriesDestination)

        For CounterDirectories = 0 To DirectoriesSource.Count - 1

            ReDim MyProcess(CounterDirectories)

            MyProcess(CounterDirectories) = New Process

            MyProcess(CounterDirectories).EnableRaisingEvents = True

            With MyProcess(CounterDirectories).StartInfo

                .FileName = RoboCopyPath
                .Arguments = """" & DirectoriesSource(CounterDirectories) & """ """ & DirectoriesDestination(CounterDirectories) & """ /MIR /MT "
                .RedirectStandardOutput = True
                .UseShellExecute = False
                .CreateNoWindow = True

            End With

            MyProcess(CounterDirectories).Start()

            MyStreamReader = MyProcess(CounterDirectories).StandardOutput

            MyText = MyText + MyStreamReader.ReadToEnd

            BgwSync.ReportProgress(CInt(10 + 80 * ((CounterDirectories + 1) / DirectoriesSource.Count)))

        Next

        CreateLogFile(MyText)

        BgwSync.ReportProgress(100)

    End Sub

    Private Sub BgwSync_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BgwSync.ProgressChanged

        PrbSync.Value = e.ProgressPercentage

        If e.ProgressPercentage = 100 Then

            LblResult.ForeColor = Color.Red
            LblResult.Text = "Completed: " + e.ProgressPercentage.ToString() + "%"

        Else

            LblResult.ForeColor = Color.Black
            LblResult.Text = "Completed: " + e.ProgressPercentage.ToString() + "%"

        End If


    End Sub

    Private Sub BgwSync_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BgwSync.RunWorkerCompleted

        If Not e.Error Is Nothing Then

            MessageBox.Show(e.Error.Message.ToString)

        ElseIf e.Cancelled Then

            LblResult.Text = "CANCELED"

        End If

        TmrSync.Stop()
        BtnSync.Enabled = True

        If Not Form.ActiveForm Is Me Or Minimized Then
            StartBlinking()
        End If

    End Sub

    Sub StartBlinking()

        Dim FlashInfo As FLASHWINFO

        With FlashInfo
            .cbSize = CInt(Convert.ToUInt32(Marshal.SizeOf(GetType(FLASHWINFO))))
            .dwFlags = CType(FLASHW_ALL Or FLASHW_TIMER, Int32)
            .hwnd = Me.Handle
            .dwTimeout = 0
            .uCount = 0
        End With

        FlashWindowEx(FlashInfo)

        BackForm = True

    End Sub

    Private Sub BtnMinimize_Click(sender As System.Object, e As System.EventArgs) Handles BtnMinimiza.Click
        'Me.SyncroLogic.WindowState = FormWindowState.Minimized
        Me.WindowState = FormWindowState.Minimized
        Minimized = True
    End Sub

    Private Sub TmrSync_Tick(sender As System.Object, e As System.EventArgs) Handles TmrSync.Tick

        CountMilisec = CountMilisec + 1

        Time = Format(Int(CountMilisec / 36000) Mod 24, "00") & ":" & _
                 Format(Int(CountMilisec / 3600) Mod 60, "00") & ":" & _
                 Format(Int(CountMilisec / 60) Mod 60, "00") & ":" & _
                 Format(CountMilisec Mod 10, "00")



        LblTime.Text = Time

    End Sub

    Private Sub SyncroLogic_Activated(sender As Object, e As System.EventArgs) Handles Me.Activated

        If BackForm Then

            StopBlinking()
            Minimized = False

        End If

    End Sub

    Sub StopBlinking()

        Dim FlashInfo As FLASHWINFO

        With FlashInfo
            .cbSize = CInt(Convert.ToUInt32(Marshal.SizeOf(GetType(FLASHWINFO))))
            .dwFlags = CType(FLASHW_STOP, Int32)
            .hwnd = Me.Handle
            .dwTimeout = 0
            .uCount = 0
        End With

        FlashWindowEx(FlashInfo)

    End Sub

    Private Sub BtnDeleteSelectedRow_Click(sender As System.Object, e As System.EventArgs) Handles BtnDeleteSelectedRow.Click

        Dim Count As Int16

        If DgvFolders2.SelectedRows.Count = 0 Then
            MsgBox("You must select a row before delete it", MsgBoxStyle.Exclamation, "Advice")
            Exit Sub
        End If

        For Count = CShort(DgvFolders2.Rows.Count - 1) To 0 Step -1

            If DgvFolders2.Rows(Count).Selected Then

                If DgvFolders2.Rows(Count).Cells.Item(1).Value.ToString = "" Then
                    RowCompleted = True
                    Source = ""
                End If

                DsPreferences.Tables.Item(0).Rows(Count).Delete()

            End If

        Next

        DgvFolders2.ClearSelection()

    End Sub

    Private Sub BtnSource_Click(sender As System.Object, e As System.EventArgs) Handles BtnSource.Click

        If Not RowCompleted Then

            MsgBox("Select first the destination folder", MsgBoxStyle.Information, "Help")
            Exit Sub

        End If

        If FbdSource.ShowDialog = Windows.Forms.DialogResult.OK Then

            Dim Row As DataRow = DsPreferences.Tables.Item(0).NewRow

            Source = FbdSource.SelectedPath

            Row("Source") = Source
            Row("Destination") = ""

            DsPreferences.Tables.Item(0).Rows.Add(Row)

            RowCompleted = False

        End If

    End Sub

    Private Sub BtnDestination_Click(sender As System.Object, e As System.EventArgs) Handles BtnDestination.Click

        If Source = "" Then

            MsgBox("Select first the Source folder", MsgBoxStyle.Information, "Help")
            Exit Sub

        End If

        If FbdDestination.ShowDialog = Windows.Forms.DialogResult.OK Then

            Destination = FbdDestination.SelectedPath

            DsPreferences.Tables.Item(0).Rows(DsPreferences.Tables.Item(0).Rows.Count - 1).Item(1) = Destination

            Source = ""

            RowCompleted = True

        End If

    End Sub

    Private Sub BtnBorrarfilas_Click(sender As System.Object, e As System.EventArgs) Handles BtnBorrarfilas.Click

        Dim Counter As Integer

        For Counter = DgvFolders2.Rows.Count - 1 To 0 Step -1

            If DgvFolders2.Rows(Counter).Cells.Item(1).Value Is "" Then
                RowCompleted = True
                Source = ""
            End If

            DsPreferences.Tables.Item(0).Rows(Counter).Delete()

        Next


    End Sub

    Private Sub BtnRestoreRows_Click(sender As System.Object, e As System.EventArgs) Handles BtnRestoreRows.Click

        Source = ""
        RowCompleted = True
        DsPreferences.Tables.Item(0).Clear()
        ReadXml(DsPreferences, AccessFiles.PathXmlFiles + "Preferences.xml")
        DgvFolders2.ClearSelection()

    End Sub

    Private Sub BtnFilesOk_Click(sender As System.Object, e As System.EventArgs) Handles BtnFilesOk.Click

        Dim DirectoryPath As String = ""

        If Not RowCompleted Then

            MsgBox("Select the Destination folder", vbInformation, "Advice")
            Exit Sub

        End If

        If Not CheckDirectories(DgvFolders2, DirectoryPath) Then

            MsgBox("The folder " + DirectoryPath + " does not exist", MsgBoxStyle.Critical, "Error")
            Exit Sub

        End If

        TbcSyncro.SelectedIndex = 0

    End Sub

    Private Sub LblDirSource_Click(sender As System.Object, e As System.EventArgs) Handles LblDirecSource.Click

        If FbdSource.ShowDialog = Windows.Forms.DialogResult.OK Then

            ShowInitDirectory()
            BtnOkOptions.Enabled = True

        End If

    End Sub

    Private Sub LblDirDestination_Click(sender As System.Object, e As System.EventArgs) Handles LblDirecDestination.Click

        If FbdDestination.ShowDialog = Windows.Forms.DialogResult.OK Then

            ShowDirDestination()
            BtnOkOptions.Enabled = True

        End If

    End Sub

    Private Sub ShowInitDirectory()

        If FbdSource.SelectedPath.Length < 70 Then

            LblDirecSource.Text = FbdSource.SelectedPath

            If DsInitDirs.Tables.Item(0).Rows.Count = 0 Then
                Dim fila As Data.DataRow
                fila = DsInitDirs.Tables.Item(0).NewRow
                DsInitDirs.Tables.Item(0).Rows.Add(fila)
            End If

            DsInitDirs.Tables.Item(0).Rows(0).SetField(0, FbdSource.SelectedPath)

        Else

            LblDirecSource.Text = TrimString(FbdSource.SelectedPath)
            ToTSource.SetToolTip(LblDirecSource, FbdSource.SelectedPath)

        End If

    End Sub

    Private Sub ShowDirDestination()


        If FbdDestination.SelectedPath.Length < 70 Then

            LblDirecDestination.Text = FbdDestination.SelectedPath

            If DsInitDirs.Tables.Item(0).Rows.Count = 0 Then
                Dim fila As Data.DataRow
                fila = DsInitDirs.Tables.Item(0).NewRow
                DsInitDirs.Tables.Item(0).Rows.Add(fila)
            End If

            DsInitDirs.Tables.Item(0).Rows(0).SetField(1, FbdDestination.SelectedPath)

        Else

            LblDirecDestination.Text = TrimString(FbdDestination.SelectedPath)
            ToTDestination.SetToolTip(LblDirecDestination, FbdDestination.SelectedPath)

        End If

    End Sub

    Private Sub LblDirOrigen_TextChanged(sender As Object, e As System.EventArgs) Handles LblDirecSource.TextChanged

        If FirstTimeInit Then
            FirstTimeInit = False
            Exit Sub
        End If

        ShowInitDirectory()

        BtnOkOptions.Enabled = True

    End Sub

    Private Sub LblDirDestination_TextChanged(sender As Object, e As System.EventArgs) Handles LblDirecDestination.TextChanged

        If FirstTimeFinish Then
            FirstTimeFinish = False
            Exit Sub
        End If

        ShowDirDestination()

        BtnOkOptions.Enabled = True

    End Sub

    Private Function TrimString(ByVal Str As String) As String

        Str = Str.Remove(64, Str.Length - 64)

        Str = Str.ToString + " ..."

        Return Str

    End Function


    Private Sub BtnOkOptions_Click(sender As System.Object, e As System.EventArgs) Handles BtnOkOptions.Click

        If Not DsInitDirs.Equals(DsCopyInitDirs) Then

            WriteXml(DsInitDirs, AccessFiles.PathXmlFiles + "Init_Directories.xml")

        End If

        If ChbConfFolders.Checked = True Then

            If Not DsPreferences.Equals(DsCopyPreferences) Then

                WriteXml(DsPreferences, AccessFiles.PathXmlFiles + "Preferences.xml")

            End If

        End If

        If ChbTime.Checked = True Then

            If DateStarted Then
                DeleteFiles()
            Else
                MsgBox("Select one day", MsgBoxStyle.Information, "Advice")
                Exit Sub
            End If

        End If

        MsgBox("Changes made properly", MsgBoxStyle.Information, "Advice")

        BtnOkOptions.Enabled = False

    End Sub

    Private Sub ChbConfFolders_Click(sender As Object, e As System.EventArgs) Handles ChbConfFolders.Click

        BtnOkOptions.Enabled = True

    End Sub

    Private Sub ChbTime_Click(sender As Object, e As System.EventArgs) Handles ChbTime.Click

        BtnOkOptions.Enabled = True

    End Sub

    Private Sub LblDate_Click(sender As System.Object, e As System.EventArgs) Handles LblDate.Click

        FrmDate.ShowDialog()

    End Sub


    Private Sub BtnShow_Click(sender As System.Object, e As System.EventArgs) Handles BtnShow.Click

        Dim Path As String
        Dim MyFile As String

        If DgvFiles.SelectedRows.Count = 0 Then
            MsgBox("You must select a file to visualize it", MsgBoxStyle.Exclamation, "Advice")
            Exit Sub
        End If

        Path = AccessFiles.PathRegistriesFolder

        MyFile = DgvFiles.Item(1, DgvFiles.CurrentRow.Index).Value.ToString

        System.Diagnostics.Process.Start(Path + MyFile)

    End Sub

    Private Sub BtnAyuda_Click(sender As System.Object, e As System.EventArgs) Handles BtnAyuda.Click

        System.Diagnostics.Process.Start("About_SyncLogic.mht")

    End Sub

    Private Sub FrmSyncLogic_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing

        If BgwSync.IsBusy Then

            If MsgBox("The synchronization is still NOT completed. If you cancel the " + _
                      "synchronization results may be unpredictable." + _
                      " Are you sure you want to close the application?", vbYesNo, "Advice") = MsgBoxResult.No Then

                BgwSync.WorkerSupportsCancellation = True
                BgwSync.CancelAsync()
                e.Cancel = True

            End If

        Else

            If Administrator Then

                If MsgBox("Are you sure you want to close the application?", vbYesNo, "Advice") = MsgBoxResult.No Then

                    e.Cancel = True

                End If

            Else

                e.Cancel = False

            End If

        End If


    End Sub


End Class


